📌 答题前先看:标准模板
import mysql.connector # 第1步:导入
db = mysql.connector.connect(...) # 第2步:连接
cursor = db.cursor() # 第3步:游标
try:
cursor.execute("...") # 第4步:执行
db.commit() # 改数据要 commit
except:
db.rollback()
cursor.close() # 第5步:关闭
db.close()
① 忘了 db.commit() —— INSERT/UPDATE/DELETE 数据没真的写入
② 没用 try-except —— 出错时数据不一致
③ fetchone vs fetchall 混用 —— 一个返回元组,一个返回列表
📝 第一部分 · 概念巩固
先用几道选择题把核心概念过一遍。
Python 连接 MySQL 数据库的 5 步流程,正确顺序 是?
📖 查看答案
✅ 答案:B
速记:"导 → 连 → 游 → 执 → 关"
逻辑:① 先导入包(才能用 mysql.connector);② 用 connect() 建立连接;③ 通过连接创建游标;④ 用游标执行 SQL;⑤ 用完关闭(先关游标后关连接)。
下列 不是 mysql.connector.connect() 必须参数的是?
📖 查看答案
✅ 答案:D · port
必须的 4 个参数:host、user、passwd、database
port 可以省略,默认是 3306(MySQL 标准端口)。除非你的 MySQL 装在非标准端口,才需要写。
下列哪种情况 不需要 调用 db.commit()?
📖 查看答案
✅ 答案:D · SELECT 不需要 commit
口诀:"读不 commit,写必 commit"
① SELECT 是读取,没改数据,不需要 commit
② INSERT/UPDATE/DELETE 是修改,必须 commit 才会真的写入数据库
不 commit 的修改只在缓冲区,关闭连接后修改全没了。
关于 fetchone() 和 fetchall(),下列说法 错误 的是?
📖 查看答案
✅ 错的是:C
① fetchall() 把所有结果一次加载到内存,数据量大时会很慢且占内存
② fetchone() 一次只取一行,只想要一行时反而更高效
选择标准:
• 只要一行 → fetchone()
• 要全部且数据量小 → fetchall()
• 数据量大但只要前 N 条 → fetchmany(N)
关于 db.rollback(),下列说法 正确 的是?
📖 查看答案
✅ 答案:C
rollback() 的作用是 "撤销":撤销所有没 commit 的修改,让数据库回到上一次 commit 后的状态。
典型场景:批量插入时其中一条出错 → rollback 把前面已经插入的也撤销 → 保证原子性(要么全成,要么全败)
这就是第 9 章学过的"事务原子性"在 Python 里的实现。
📖 第二部分 · 读代码(预测结果)必考
本部分给一段代码,不要急着运行,先动脑分析执行流程,再对照答案。
下面的代码运行不会报错,但执行完后再到 MySQL 中查询 s 表,能查到 's13' 这条新记录吗?
import mysql.connector
db = mysql.connector.connect(
host='localhost', user='root',
passwd='123456', database='teaching'
)
cursor = db.cursor()
cursor.execute("INSERT INTO s VALUES('s13','测试','男',20,'软件','信息学院')")
# 注意:这里没有 db.commit()
cursor.close()
db.close()
📖 查看答案
❌ 查不到!
execute() 执行后,修改只在缓冲区,并没有真的写入 MySQL。必须 db.commit() 才会"提交"到数据库。这段代码没 commit 就 close,缓冲区的修改全部丢失。
在 cursor.close() 之前加一行 db.commit()
"忘了 commit"是初学者最容易踩的坑,期末考试也最爱考。记住:"读不 commit,写必 commit"、"提交才落盘,不提白干"
假设 s 表中有 5 个 age >= 20 的学生。下面三段代码 分别打印什么?
# --- 第 1 段 ---
cursor.execute("SELECT * FROM s WHERE age >= 20")
r1 = cursor.fetchone()
print(type(r1), len(r1) if r1 else 0)
# --- 第 2 段 ---
cursor.execute("SELECT * FROM s WHERE age >= 20")
r2 = cursor.fetchall()
print(type(r2), len(r2))
# --- 第 3 段 ---
cursor.execute("SELECT * FROM s WHERE age >= 20")
r3 = cursor.fetchmany(3)
print(type(r3), len(r3))
📖 查看答案
取 一行,返回 元组。学生表 s 共 6 个字段。
取 全部 5 行,返回 列表(列表里是 5 个元组)。
取 前 3 行,返回 列表。
① fetchone 返回 tuple,其他两个返回 list
② fetchall 取全部,fetchmany(n) 取 n 个
③ 一行的长度 = 字段数量(6),返回的是 列表中元组的个数
假设 s 表的主码是 sno,且已经存在 's1'。运行下面代码,会输出什么?数据库里 s5 的记录会被插入吗?
import mysql.connector
db = mysql.connector.connect(
host='localhost', user='root',
passwd='123456', database='teaching'
)
cursor = db.cursor()
try:
# 第 1 条:s5 是新学号(假设原本不存在)
cursor.execute("INSERT INTO s VALUES('s5','张三','男',20,'计算机','信息学院')")
# 第 2 条:s1 已经存在(主码冲突,会抛异常!)
cursor.execute("INSERT INTO s VALUES('s1','李四','女',19,'数学','理学院')")
db.commit()
print("全部插入成功")
except:
db.rollback()
print("插入失败已回滚")
cursor.close()
db.close()
📖 查看答案
① 第 1 条 INSERT s5 → 没报错(s5 不存在)
② 第 2 条 INSERT s1 → 抛异常(s1 已存在,主码冲突)
③ 跳到 except 块
④ 执行 db.rollback() → 撤销所有未提交的修改(包括第 1 条的 s5)
⑤ 输出 "插入失败已回滚"
s5 不会被插入! 因为 rollback 把第 1 条 INSERT 也撤销了。
"要么全成功,要么全失败" —— 不会出现"一半成功一半失败"的中间状态。这就是第 9 章学过的事务原子性,在 Python 里的实现。
💻 第三部分 · 写代码必考
本部分要求 根据需求自己写 Python 代码。先在纸上画出框架,再对照答案。
写一段 Python 代码,连接 teaching 数据库(host=localhost, user=root, passwd=123456),查询学生总数并打印。
📖 查看答案
解题思路:① 5 步流程;② SQL: SELECT COUNT(*) FROM s;③ 结果一行一列,用 fetchone()
import mysql.connector
db = mysql.connector.connect(
host='localhost',
user='root',
passwd='123456',
database='teaching'
)
cursor = db.cursor()
cursor.execute("SELECT COUNT(*) FROM s")
result = cursor.fetchone() # 返回元组,如 (12,)
print("学生总数:", result[0])
cursor.close()
db.close()
① 查询不需要 commit
② fetchone() 返回元组,如 (12,),要用 result[0] 取数字
写一段 Python 代码,用 try-except 模板 向 s 表中插入两条记录:
- ('s20', '陈小明', '男', 20, '软件', '信息学院')
- ('s21', '李小红', '女', 19, '数学', '理学院')
要求:全部成功才提交;有一条失败就全部回滚。
📖 查看答案
import mysql.connector
db = mysql.connector.connect(
host='localhost', user='root',
passwd='123456', database='teaching'
)
cursor = db.cursor()
sql1 = "INSERT INTO s VALUES('s20','陈小明','男',20,'软件','信息学院')"
sql2 = "INSERT INTO s VALUES('s21','李小红','女',19,'数学','理学院')"
try:
cursor.execute(sql1)
cursor.execute(sql2)
db.commit() # 全部成功才 commit
print("全部插入成功")
except Exception as e:
db.rollback() # 任何一条失败就回滚
print("插入失败:", e)
cursor.close()
db.close()
① 用 try 包住所有的 execute 和 commit
② 用 except 调用 rollback
这样能保证 原子性(要么全成,要么全败)。
写一段 Python 代码,把 s 表中所有"信息学院"的学生年龄(age)都增加 1,并打印出影响了多少行。
📖 查看答案
import mysql.connector
db = mysql.connector.connect(
host='localhost', user='root',
passwd='123456', database='teaching'
)
cursor = db.cursor()
sql = "UPDATE s SET age = age + 1 WHERE dept = '信息学院'"
try:
cursor.execute(sql)
db.commit()
print("成功更新", cursor.rowcount, "行")
except Exception as e:
db.rollback()
print("更新失败:", e)
cursor.close()
db.close()
cursor.rowcount 返回 最近一次 execute 受影响的行数。对 UPDATE/DELETE 特别有用,可以判断"到底有几条记录被改了"。
写一段 Python 代码,查询 s 表中所有"女"生的学号(sno)和姓名(sn),逐行打印,格式如:s1 | 王彤。
📖 查看答案
import mysql.connector
db = mysql.connector.connect(
host='localhost', user='root',
passwd='123456', database='teaching'
)
cursor = db.cursor()
cursor.execute("SELECT sno, sn FROM s WHERE sex = '女'")
results = cursor.fetchall() # 取所有结果
# 遍历打印
for row in results:
print(row[0], "|", row[1])
cursor.close()
db.close()
① 查询不需要 commit
② fetchall() 返回 列表,列表里每个元素是一行的元组
③ 元组用下标取字段:row[0] 是 sno,row[1] 是 sn
④ 也可以解包:for sno, sn in results: print(sno, "|", sn) 更优雅
🎯 第四部分 · 综合大题期末重点
本部分把整章知识揉到一起,是 必考综合大题。
写一个完整的 Python 程序,实现以下需求:
- 插入一名新学生:('s30','王晓明','男',20,'计算机','信息学院')
- 修改"陈小红"的专业为"软件"
- 查询并打印所有"信息学院"的学生(逐行显示)
- 使用 try-except 处理事务,出错回滚
- 所有数据库操作完成后,关闭游标和连接
📖 查看答案
解题思路:
① 一次连接,做三件事(INSERT + UPDATE + SELECT)
② INSERT 和 UPDATE 是修改,需要 commit + try-except
③ SELECT 是查询,不需要 commit
import mysql.connector
# 第 1 步:连接数据库
db = mysql.connector.connect(
host='localhost',
user='root',
passwd='123456',
database='teaching'
)
cursor = db.cursor()
# 第 2 步:执行修改类操作(INSERT + UPDATE),用 try-except 保证原子性
try:
# 插入新学生
cursor.execute(
"INSERT INTO s VALUES('s30','王晓明','男',20,'计算机','信息学院')"
)
# 修改专业
cursor.execute(
"UPDATE s SET maj = '软件' WHERE sn = '陈小红'"
)
db.commit()
print("插入和修改成功!")
except Exception as e:
db.rollback()
print("操作失败,已回滚:", e)
# 第 3 步:查询所有信息学院学生
print("\n--- 信息学院学生列表 ---")
cursor.execute("SELECT * FROM s WHERE dept = '信息学院'")
results = cursor.fetchall()
for row in results:
print(row)
# 第 4 步:关闭游标和连接
cursor.close()
db.close()
print("\n程序执行完毕")
① "导→连→游→执→关" 5 步流程
② INSERT 和 UPDATE 放在一个 try 里,保证原子性
③ SELECT 单独执行,不在 try 里(查询不需要事务保护)
④ fetchall() 取全部结果,然后用 for 循环遍历
① 忘了 db.commit() → 数据没真的写入
② 把 SELECT 也放在 try 里 → 不会出错,但没必要
③ 忘了 close() → 短期没事,长期会耗尽数据库连接资源
📝 复习重点回顾
通过本次练习,你应该已经:
- ✅ 掌握 5 步流程、commit/rollback、fetch 三件套
- ✅ 能 读懂 Python+MySQL 代码并预测结果
- ✅ 能 按需求写出 完整的 CRUD 程序
- ✅ 会用 try-except 处理事务,保证数据一致性
按出现频率排序:
- 写一段完整的 Python 连 MySQL 代码(综合大题,分值最高)
- commit 和 rollback 的作用(必考)
- fetchone vs fetchall vs fetchmany 的区别
- 5 步流程(顺序题)
- 什么时候要 commit(读不要、写要)
① "导 → 连 → 游 → 执 → 关" —— 5 步流程
② "读不 commit,写必 commit" —— 何时提交
③ "try 执行 commit,except 写 rollback" —— 标准模板
④ "fetchone 一行,fetchall 全部" —— 查询方法
⑤ "提交才落盘,不提白干" —— commit 的意义
🎓 整门课程完结!
恭喜你完成了《数据库原理及应用教程(MySQL)》整本教材的所有练习!
从第 1 章的关系模型基础,到本章的 Python 编程实战,你已经掌握了:
- ✅ SQL 查询(CRUD、连接、子查询、视图)
- ✅ 数据库设计(E-R 图、规范化、物理设计)
- ✅ 数据库管理(安全、并发、备份恢复)
- ✅ 高级编程(存储过程、函数、触发器、事件)
- ✅ 实际应用(用 Python 连接 MySQL 开发程序)
🎉 期末考个好成绩 💪 全书完